import { Request, Response } from "express";
import { uploadAvatarImg } from "../../multer/upload";
import { uploadExcel } from "../../multer/uploadExcel";
import classesService from "../../service/classesService";
import collegeService from "../../service/collegeService";
import majorService from "../../service/majorService";
import studentService from '../../service/studentService'
import { encryption, decrypt, createToken, processData, checkDate } from '../../utils/index'
import {
  validateRegisterForm, validateLoginForm,
  validateUpdateInfoForm, validatePhoneAndEmail,
  validateExcelForm, validateAdminssionDate
} from './validate'

class studentController {

  // 登录
  async login(req: Request, res: Response) {
    // 验证表单参数
    let validateRes = validateLoginForm(req.body)
    if (validateRes) return res.gem(validateRes)
    // 查找账号(account为学号)
    const { account, password } = req.body
    const userInfo = await studentService.findOneByStu_num(account.toLocaleLowerCase())
    if (!userInfo) return res.gem('账号不存在！')
    // 密码解密进行对比
    const isRight = decrypt(password, String(userInfo.password)) // 密码比较 
    if (!isRight) return res.gem('密码错误！')
    // 用户状态
    if (!userInfo.state) return res.gem('账号已被禁用！')
    // 生成 token
    const token = createToken(Number(userInfo.id))
    delete userInfo.password
    res.gsmdt(userInfo, token)
  }

  // 创建
  async register(req: Request, res: Response) {
    const form = req.body
    console.log(form);

    // 验证表单参数
    const validateRes = validateRegisterForm(form)
    if (validateRes) return res.gem(validateRes)
    // 先查询账号是否存在
    form.stu_num = `gk${form.stu_num}`
    const student = await studentService.findOneByStu_num(form.stu_num)
    if (student) return res.gem('账号已存在！')
    const classRes = await classesService.findByClassesName(form.class)
    // 处理默认数据
    form.password = '123456'
    form.state = form.state ? Boolean(form.state) : true
    form.role = 2
    form.password = encryption(form.password)
    form.class_id = classRes.id.toString()
    // 保存数据倒数库
    const saveResult = await studentService.save(form)
    if (saveResult) {
      res.gsm('创建成功！')
    }
  }

  // 分页查询所有 student 用户
  async findAll(req: Request, res: Response) {
    // const total = await studentService.studentCount()
    // let page_num = parseInt(req.query.page_num) || 1 // 如果page_num为0就默认为1
    // let page_size = parseInt(req.query.page_size) || 10

    // // 计算skip
    // let skip = (page_num - 1) * page_size
    // const result = await studentService.find(skip, page_size)
    // result.forEach(item => delete item.password) // 不返回密码
    // res.gsmdl(total, result)

    const datas = await studentService.findAll()
    res.gsmd(datas)
  }

  // 根据id查找 student 用户
  async findById(req: Request, res: Response) {
    const { id } = req.params
    const result = await studentService.findById(id)
    if (!result) return res.gem('查询失败！')
    delete result.password
    res.gsmd(result)
  }

  // 根据学号查找 student 用户
  async findByStu_num(req: Request, res: Response) {
    const { stu_num } = req.params
    if (!stu_num) return res.gem('请输入学号')
    const result = await studentService.findOneByStu_num(stu_num)
    if (!result) return res.gem('查无此学生，请检查学号是否正确！')
    result.major = result.classes.major_name
    result.class = result.classes.class_name
    result.college = result.classes.college_name
    delete result.password
    res.gsmd(result)
  }

  // 更新头像
  async updateAvatar(req: Request, res: Response) {
    const { id, base64 } = req.body
    const updateRes = await studentService.updateAvatar(id, base64)
    if (updateRes.affected < 1) return res.gem('更新头像失败！')
    res.gsm('更新头像成功！')
  }

  // 根据手机号码查找 student 用户
  async findByPhone(req: Request, res: Response) {
    const { phone } = req.params
    const result = await studentService.findByPhone(phone)
    if (!result) return res.gem('查无此学生，请检查手机号码是否正确！')
    delete result.password
    res.gsmd(result)
  }

  // 修改密码
  async updatePassword(req: Request, res: Response) {
    const form = req.body
    if (form.newPass.length < 6 || form.newPass.length > 10) return res.gem('密码长度必须是6-10之间！')
    if (form.newPass !== form.checkPass) return res.gem('两次输入的密码不一致！')
    const user = await studentService.findById(form.id)
    // 校验密码
    const isRight = decrypt(form.oldPass, user.password)
    if (!isRight) return res.gem('旧密码错误！')

    // 密码加密存储
    form.checkPass = encryption(form.checkPass)
    const result = await studentService.updatePassWord(form.id, form.checkPass)
    if (result.affected < 1) return res.gem('修改密码失败！')
    res.gsm('修改密码成功！')
  }

  // 修改个人信息
  async updateInfo(req: Request, res: Response) {
    const form = req.body
    // 表单验证
    const errorMsg = validateUpdateInfoForm(form)
    if (errorMsg) return res.gem(errorMsg)
    // 修改信息
    // 先取出id，然后删除form中的id（数据库中为_id，这里为id，不一样会导致修改时添加id字段）
    const userId = form.id
    delete form.id
    if (form.class) {
      const classes = await classesService.findByClassesName(form.class)
      form.class_id = classes.id.toString()
    }
    const result = await studentService.updateInfo(userId, form)
    if (result.affected < 0) return res.gem('修改信息失败！')
    const user = await studentService.findById(userId)
    res.gsmd(user, '信息修改成功！')
  }

  // 上传头像
  async uploadAva(req: Request, res: Response) {
    try {
      let uploadData: any = await uploadAvatarImg(req, res)
      // console.log('uploadRes: ',uploadData);
      const uploadRes = await studentService.updateAvatar(uploadData.id, uploadData.img_src)
      if (uploadRes.affected >= 1) {
        res.gsm('上传头像成功！')
      }
    } catch (err) {
      if (err.error) {
        res.gem(err.error)
      } else {
        res.gem(err, '上传失败，图片大小限制为2mb！')
      }
    }
  }

  // 根据姓名关键词模糊查询（分页）
  async findByNameKey(req: Request, res: Response) {
    const { name } = req.body
    const page_num = parseInt(req.body.page_num) || 1
    const page_size = parseInt(req.body.page_size) || 10

    const skip = (page_num - 1) * page_size
    const count = await studentService.findByNameKeyCount(name)
    const users = await studentService.findByNameKey(name, skip, page_size)
    if (!users) res.gem('查无数据！')
    // 根据class_id，查询对应班级信息
    for (let i = 0; i < users.length; i++) {
      if (users[i]?.class_id !== undefined) {
        const classes: any = await classesService.findById(users[i]?.class_id)
        users[i].classes = classes
        users[i].major = classes.major_name
        users[i].class = classes.class_name
        users[i].college = classes.college_name
      } else {
        users[i].classes = {}
      }
    }
    res.gsmdl(count, users)
  }

  // 根据所属学院关键词模糊查询（分页）
  async findByCollegeKey(req: Request, res: Response) {
    const { college } = req.body
    const page_num = parseInt(req.body.page_num) || 1
    const page_size = parseInt(req.body.page_size) || 10

    const skip = (page_num - 1) * page_size

    const count = await studentService.findByCollegeKeyCount(college)
    const users = await studentService.findByCollegeKey(college, skip, page_size)

    if (!users) res.gem('查无数据！')
    // 根据class_id，查询对应班级信息
    for (let i = 0; i < users.length; i++) {
      if (users[i]?.class_id !== undefined) {
        const classes: any = await classesService.findById(users[i]?.class_id)
        users[i].classes = classes
        users[i].major = classes.major_name
        users[i].class = classes.class_name
        users[i].college = classes.college_name
      } else {
        users[i].classes = {}
      }
    }
    res.gsmdl(count, users)
  }

  // 根据所属专业关键词模糊查询（分页）
  async findByMajorKey(req: Request, res: Response) {
    const { major } = req.body
    const page_num = parseInt(req.body.page_num) || 1
    const page_size = parseInt(req.body.page_size) || 10

    const skip = (page_num - 1) * page_size

    const count = await studentService.findByMajorKeyCount(major)
    const users = await studentService.findByMajorKey(major, skip, page_size)

    if (!users) res.gem('查无数据！')
    // 根据class_id，查询对应班级信息
    for (let i = 0; i < users.length; i++) {
      if (users[i]?.class_id !== undefined) {
        const classes: any = await classesService.findById(users[i]?.class_id)
        users[i].classes = classes
        users[i].major = classes.major_name
        users[i].class = classes.class_name
        users[i].college = classes.college_name
      } else {
        users[i].classes = {}
      }
    }
    res.gsmdl(count, users)
  }

  // 根据 id 进行删除
  async deleteById(req: Request, res: Response) {
    const { id } = req.params
    const user = await studentService.findById(id)
    if (!user) return res.gem('该用户不存在！')
    const result = await studentService.deleteById(id)
    if (result.affected >= 1) {
      return res.gsm('删除用户成功！')
    } else {
      return res.gem('删除用户失败！')
    }
  }

  // 修改用户状态
  async updateState(req: Request, res: Response) {
    const id = req.params.id
    const user = await studentService.findById(id)
    if (!user) return res.gem('该用户不存在')
    const result = await studentService.updateState(id, !user.state)
    if (result.affected < 1) return res.gem('用户状态修改失败！')
    res.gsm('用户状态修改成功！')
  }

  // 上传excel文件，批量创建用户
  async createManyUser(req: Request, res: Response) {

    try {
      const excelData: any = await uploadExcel(req)
      const cnNameToEnName = {
        姓名: 'name',
        学号: 'stu_num',
        性别: 'gender',
        手机号码: 'phone',
        邮箱: 'email',
        所属院系: 'college',
        所属专业: 'major',
        所属班级: 'class',
        入学年份: 'admission_date',
        层次: 'level',
      }
      let isOk = true
      // 校验是否有需要的表头，只需要判断第一个对象即可
      Object.keys(cnNameToEnName).forEach((k: any) => {
        if (!excelData[0].hasOwnProperty(k)) {
          isOk = false
          return res.gem(`该文件表头缺失【${k}】字段，请重新上传！`)
        }
      })
      // 处理表头格式
      const newExcelData = processData(cnNameToEnName, excelData)

      let user: any = {}
      // 获取全部学院、专业、班级，后续校验所属学院、专业、班级是否存在
      const colleges = await collegeService.findAll()
      const majors = await majorService.findAll()
      const classes = await classesService.findAll()

      const college_names = colleges.map(item => item.college_name)
      const major_names = majors.map(item => item.major_name)
      const class_names = classes.map(item => item.class_name)

      newExcelData.forEach(async (item: any) => {
        // 校验必填项是否为空
        const msg = validateExcelForm(item)
        if (isOk && msg) {
          isOk = false
          return res.gem(msg)
        }

        // 校验学号格式（必须以 gk 结尾）
        if (isOk && !item.stu_num.startsWith('gk')) {
          return res.gem(`文件中有不符合规则的学号 ——【${item.stu_num}】，请检查后重新上传！`)
        }
        // 校验手机号码和邮箱（可以没有，但有则必须正确）
        const validateRes = validatePhoneAndEmail(item)
        if (isOk && validateRes?.msg) {
          isOk = false
          return res.gem(`文件中有不符合规则的${validateRes.msg} ——【${validateRes.value}】，请检查后重新上传！`)
        }

        // 验证入学年份日期是否正确
        const isDateOk = validateAdminssionDate(item.admission_date)
        if (isOk && !isDateOk) {
          isOk = false
          return res.gem(`文件中有不符合规范的入学年份 ——【${item.admission_date}】，请检查后重新上传！`)
        }

        // 校验性别是否正确
        const isGenderOk = item.gender === '男' || item.gender === '女'
        if (isOk && !isGenderOk) {
          isOk = false
          return res.gem(`文件中有填写错误的性别 ——【${item.gender}】，请检查后重新上传！`)
        }

        // 校验层次是否正确
        const isLevelOk = item.level === '本科' || item.level === '专科'
        if (isOk && !isLevelOk) {
          isOk = false
          return res.gem(`文件中有填写错误的层次 ——【${item.level}】，请检查后重新上传！`)
        }

        // 校验所属学院是否存在
        const isCollege = college_names.find(c => c === item.college)
        if (isOk && !isCollege) {
          isOk = false
          return res.gem(`文件中某所属学院【${item.college}】填写有误，请检查后重新上传！`)
        }

        // 校验所属专业是否存在
        const isMajor = major_names.find(c => c === item.major)
        if (isOk && !isMajor) {
          isOk = false
          return res.gem(`文件中某所属专业【${item.major}】填写有误，请检查后重新上传！`)
        }

        // 校验所属班级是否存在
        const isClasses = class_names.find(c => c === item.class)
        if (isOk && !isClasses) {
          isOk = false
          return res.gem(`文件中某所属班级【${item.class}】填写有误，请检查后重新上传！`)
        }

        // 校验学号是否已存在
        if (isOk) {
          const findRes = await studentService.findOneByStu_num(item.stu_num)
          if (isOk && findRes) {
            isOk = false
            user = findRes
            return
          }
        }

      })

      if (isOk) {
        setTimeout(async () => {
          if (Object.keys(user).length !== 0) {
            return res.gem(`文件中的账号【${user.stu_num}】已存在，请重新上传！`)
          } else {
            newExcelData.forEach((item: any) => {
              // 处理数据
              item.phone = String(item.phone)
              item.password = encryption('123456')
              item.admission_date = item.admission_date.split('.').join('-')
              item.state = true
              item.role = 2
            })
            const saveRes = await studentService.saveMany(newExcelData)
            if (saveRes.length !== 0) {
              res.gsm('批量创建用户成功！')
            } else {
              res.gem('批量创建用户失败！')
            }
          }
        }, 10)
      }
    } catch (error) {
      if (error.msg) {
        res.gem(error.msg)
      }
    }
  }
}

export default new studentController()